/*
 * version.c
 *
 *  Created on: 2018��8��16��
 *      Author: Administrator
 */


#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>

#include "bit_info.h"

unsigned char global_bit[32]={0};

#define CK_TIME 1

/*
******************
******************
this is common functions used by all
******************
******************
*/
//get info in the proc file
void getInfor(char *path, char *name, char infor[])
{
	int fd = open(path, O_RDONLY);
	char store[2000];
	int k = 0;
	char *p = NULL;

	read(fd, store, sizeof(store));
	close(fd);
	//get store name
	p = strstr(store, name);

	//skip title
	while ((*p < '0') || (*p > '9'))
	{
		p++;
	}
	//get number
	while ((*p >= '0') && (*p <= '9'))
	{
		infor[k] = *p;
		k++;
		p++;
	}
	infor[k] = '\0';

	float fInfor = (float) atoi(infor);
	fInfor = fInfor / 1024;
	gcvt(fInfor, 5, infor);
}

//get number after space
void getInforAftSpace(char *path, char *name, char infor[])
{
	int fd = open(path, O_RDONLY);
	char store[2000];
	int k = 0;
	char *p = NULL;

	read(fd, store, sizeof(store));
	close(fd);
	//get point of the row
	p = strstr(store, name);

	//skip title
	while ((*p < '0') || (*p > '9'))
	{
		p++;
	}
	//get numbers
	while ((*p >= '0') && (*p <= '9'))
	{
		infor[k] = *p;
		k++;
		p++;
	}
	infor[k] = '\0';
}

//get info node for cpu
void getInforNotd(char *path, char *name, char infor[])
{
	int fd = open(path, O_RDONLY);
	char store[2000];
	int k = 0;
	char *p = NULL;

	read(fd, store, sizeof(store));
	close(fd);
	//get point of the row
	p = strstr(store, name);

	//skip title
	do
	{
		p++;
	} while (*p != ':');
	p += 2;
	//get number
	while (*p != '\n')
	{
		infor[k] = *p;
		k++;
		p++;
	}
	infor[k] = '\0';
}


void getSysVersion(char *path, char *name, char infor[])
{
	int fd = open(path, O_RDONLY);
	char store[2000];
	int k = 0;
	char *p = NULL;

	read(fd, store, sizeof(store));
	close(fd);
	//get point of the row
	p = strstr(store, name);

	//get numbers
	while (*p != '\n' && *p != ')')
	{
		infor[k] = *p;
		k++;
		p++;
	}
	infor[k++] = ')';
	infor[k] = '\0';
}

//transfer float to unsigned char
unsigned char transfer(float temp)
{
	unsigned char result;
	char buff[100];
	int before,end;
	memset(buff,0,sizeof(buff));
	sprintf(buff,"%.2f",temp);
//	printf("buff is %s temp is %f\n",buff,temp);
	sscanf(buff,"%d.%d",&before,&end);
	result=(before<<4)|end;
//	printf("result is 0x%x before is %d end is %d\n",result,before,end);
	return result;

}

/*
 ****************************
 ****************************
 ****************************
 ****************************
 ****************************
 This is cpu basic info,including bios,os,driver,cpu model,ramspeed
 ****************************
 ****************************
 ****************************
 ****************************
 ****************************
 */

//get bios version
unsigned char getbiosVersion()
{
	FILE *fstream=NULL;
	char buff[1024];
	int errno=0;
	float biosVersion=0;
	unsigned char result=0;
	memset(buff,0,sizeof(buff));
	if(NULL==(fstream=popen("dmidecode -t bios | grep 'BIOS Revision' ","r")))
	{
		fprintf(stderr,"execute command failed:%s",strerror(errno));
		return -1;
	}
	while(NULL!=fgets(buff,sizeof(buff),fstream))
	{
		sscanf(buff, "%*s %*s %f", &biosVersion);
//		printf("BIOS version is %f\n",biosVersion);
	}
	pclose(fstream);
	result=transfer(biosVersion);
	return result;
}

//get linux-os version
unsigned char getosVersion()
{
	FILE *fstream=NULL;
	char buff[1024];
	int errno=0;
	int i,flag=0;
	unsigned char result=0;
	memset(buff,0,sizeof(buff));
	if(NULL==(fstream=popen("uname -r","r")))
	{
		fprintf(stderr,"execute command failed:%s",strerror(errno));
		return -1;
	}
	while(NULL!=fgets(buff,sizeof(buff),fstream))
	{
		for(i=0;buff[i]!='\0';i++)
		{
			if(buff[i]=='.'&&flag==0)
			{
				flag=1;
				continue;
			}
			if(buff[i]=='.'&&flag==1)
			{
				buff[i]='\0';
				break;
			}
		}

	}
	pclose(fstream);
//	printf("kernel version is %s\n",buff);
	result=transfer((float)atof(buff));
	return result;
}

//get driver version
unsigned char getdriverVersion()
{
	unsigned char result=0;
	float temp=1.0;
	result=transfer(temp);
	return result;
}

//this is ascii of intel xeon E5V4
int getcpuModel()
{
	int result=0x45355634;
	return result;
}

//ram speed is 2400MT/S
int getramSpeed()
{
	int result=0x960;
	return result;
}

//ram size is 32GB
int getramSize()
{
	int result=0x8000;
	return result;
}

//ssd size is 64GB
int getssdSize()
{
	int result=0x10000;
	return result;
}



/*
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 this is for hardware usage,including cpu,memory,ssd,network,cpu temp
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 ***********************************
 */
//get cpu use ratio
unsigned char getCpuUseRatio()
{
	FILE *fp;
	char buffer[1024];
	size_t buf;
	float useRatio;
	float user = 0, nice = 0, sys = 0, idle = 0, iowait = 0;
	float all1,all2,idle1,idle2;
	unsigned char result=0;
	fp = fopen("/proc/stat", "r");
	buf = fread(buffer, 1, sizeof(buffer), fp);
	if (buf == 0)
	{
		return 0;
	}
	buffer[buf] = '\0';
	sscanf(buffer, "%*s %f %f %f %f %f", &user, &nice, &sys, &idle, &iowait);

	if (idle <= 0)
	{
		idle = 0;
	}
	all1=user+nice+sys+idle+iowait;
	idle1=idle;
	rewind(fp);

	sleep(CK_TIME);
	memset(buffer,0,sizeof(buffer));
	user=0;
	nice=0;
	sys=0;
	idle=0;
	iowait=0;
	buf = fread(buffer, 1, sizeof(buffer), fp);
	if (buf == 0)
	{
		return 0;
	}
	buffer[buf] = '\0';
	sscanf(buffer, "%*s %f %f %f %f %f", &user, &nice, &sys, &idle, &iowait);
	if (idle <= 0)
	{
		idle = 0;
	}

	all2=user+nice+sys+idle+iowait;
	idle2=idle;
	fclose(fp);

	useRatio=all2-all1;
	useRatio = 100 * (useRatio-(idle2-idle1)) / useRatio;
	if (useRatio > 100)
	{
		useRatio = 100;
	}
//	printf("cpu use ratio is %f\n",useRatio);
	result=(unsigned char)(useRatio*100);
	return result;
}


//get mem use ratio
unsigned char getMemUseRatio()
{
	float total_mem,free_mem;
	char totalMem[20], freeMem[20];
	float memUseRatio;
	unsigned char result=0;
	getInfor("/proc/meminfo", "MemTotal", totalMem);
	getInfor("/proc/meminfo", "MemFree", freeMem);
	total_mem = (float) atoi(totalMem);
	free_mem = (float) atoi(freeMem);
	memUseRatio= 100*(1 - free_mem / total_mem);
//	printf("memUseRatio is %f\n",memUseRatio);
	result=(unsigned char)memUseRatio;
	return result;
}

//get disk usage
int getDiskUsage()
{
	FILE *fstream=NULL;
	char buff[1024];
	int errno=0;
	int result=0;
	float diskUsage=0;
	memset(buff,0,sizeof(buff));
	if(NULL==(fstream=popen("df -h | grep /dev/mapper/kylin-home","r")))
	{
		fprintf(stderr,"execute command failed:%s",strerror(errno));
		return -1;
	}
	while(NULL!=fgets(buff,sizeof(buff),fstream))
	{
		sscanf(buff, "%*s %*s %*s %*s %f", &diskUsage);
//		printf("Disk Usage is %f\n",diskUsage);
	}
	pclose(fstream);
	result=(int)(0x10000*diskUsage);
	return result;
}



//get netcard usage
float getNetInfo(char *name,int flag)
{
	char shell_buffer[100];
	char result_buffer[1000];
	float curRatio;
	float netUsage=0;
	float cx5BandWidth=40960; //CX5 band width 40Gbps
	float intelBandWidth=1000; //Intel i350 band width 1000Mbps

	float rxBytes1=0,txBytes1=0,rxBytes2=0,txBytes2=0;
	float rxPkg1=0,txPkg1=0,rxPkg2=0,txPkg2=0;

	FILE *fstream=NULL;
	char buff[1024];
	int errno=0;

	memset(buff,0,sizeof(buff));
	sprintf(shell_buffer,"cat /proc/net/dev| grep %s",name);
	sprintf(result_buffer,"    %s: %%f %%f %%f %%f %%f %%f %%f %%f %%f",name);

	if(NULL==(fstream=popen(shell_buffer,"r")))
	{
		fprintf(stderr,"execute command failed:%s",strerror(errno));
		return -1;
	}
	while(NULL!=fgets(buff,sizeof(buff),fstream))
	{
		sscanf(buff, "%*s %f %f %*s %*s %*s %*s %*s %*s %f %f", &rxBytes1,&rxPkg1,&txBytes1,&txPkg1);
	}

	pclose(fstream);
	sleep(CK_TIME);
	memset(buff,0,sizeof(buff));
	if(NULL==(fstream=popen(shell_buffer,"r")))
	{
		fprintf(stderr,"execute command failed:%s",strerror(errno));
		return -1;
	}

	while(NULL!=fgets(buff,sizeof(buff),fstream))
	{
		sscanf(buff, "%*s %f %f %*s %*s %*s %*s %*s %*s %f %f", &rxBytes2,&rxPkg2,&txBytes2,&txPkg2);
	}
	pclose(fstream);
	curRatio=(rxBytes2-rxBytes1+txBytes2-txBytes1)*8/2;

	if(flag==1)
	{
		netUsage = curRatio/cx5BandWidth;
	}
	else
	{
		netUsage = curRatio/intelBandWidth;
	}
	if (netUsage > 100)
	{
		netUsage = 100;
	}
	return netUsage;
}

//get netcard cx5-0 usage
unsigned char getcx5Net0Usage()
{
	unsigned char result=0;
	float cx5netUsage0=getNetInfo("enp2s0f0",1);
	result=(unsigned char)cx5netUsage0;
	return result;
}

//get netcard cx5-1 usage
unsigned char getcx5Net1Usage()
{
	unsigned char result=0;
	float cx5netUsage1=getNetInfo("enp2s0f1",1);
	result=(unsigned char)cx5netUsage1;
	return result;
}

//get netcard intel-0 usage
unsigned char getintelNet0Usage()
{
	unsigned char result=0;
	float netUsage0=getNetInfo("enp9s0f0",0);
	result=(unsigned char)netUsage0;
	return result;
}

//get netcard intel-1 usage
unsigned char getintelNet1Usage()
{
	unsigned char result=0;
	float netUsage1=getNetInfo("enp9s0f1",0);
	result=(unsigned char)netUsage1;
	return result;
}

//get netcard intel-2 usage
unsigned char getintelNet2Usage()
{
	unsigned char result=0;
	float netUsage2=getNetInfo("enp9s0f2",0);
	result=(unsigned char)netUsage2;
	return result;
}

//get netcard intel-3 usage
unsigned char getintelNet3Usage()
{
	unsigned char result=0;
	float netUsage3=getNetInfo("enp9s0f3",0);
	result=(unsigned char)netUsage3;
	return result;
}

//get cpu temperature
unsigned char getCpuTemp()
{
	FILE *fstream=NULL;
	char buff[1024];
	int errno=0;
	int temp=0;
	unsigned char result=0;
	memset(buff,0,sizeof(buff));
	if(NULL==(fstream=popen("sensors | grep Physical","r")))
	{
		fprintf(stderr,"execute command failed:%s",strerror(errno));
		return -1;
	}
	while(NULL!=fgets(buff,sizeof(buff),fstream))
	{
		sscanf(buff, "%*s %*s %*s %d.", &temp);
	}
	pclose(fstream);
//	printf("CPU temperature is %d\n",temp);
	result=(unsigned char)(temp+100);
	return result;
}

int bit_send()
{
	char buff[1024];
	int i;
	int temp;
	memset(buff,0,sizeof(buff));

	if(global_bit[0]==0)
	{
		global_bit[0]=getbiosVersion();
	}
	if(global_bit[1]==0)
	{
		global_bit[1]=getosVersion();
	}
	if(global_bit[2]==0)
	{
		global_bit[2]=getdriverVersion();
	}
	if(global_bit[3]==0)
	{
		temp=getcpuModel();
		temp=htonl(temp);
		memcpy((void*)(global_bit+3),(void*)&temp,sizeof(int));
	}
	if(global_bit[9]==0)
	{
		temp=getramSpeed();
		temp=htonl(temp);
		memcpy((void*)(global_bit+7),(void*)&temp,sizeof(int));
	}
	if(global_bit[13]==0)
	{
		temp=getramSize();
		temp=htonl(temp);
		memcpy((void*)(global_bit+11),(void*)&temp,sizeof(int));
	}
	if(global_bit[16]==0)
	{
		temp= getssdSize();
		temp=htonl(temp);
		memcpy((void*)(global_bit+15),(void*)&temp,sizeof(int));
	}

	global_bit[19]= getCpuUseRatio();
	global_bit[20]=getMemUseRatio();

	if(global_bit[22]==0)
	{
		temp= getDiskUsage();
		temp=htonl(temp);
		memcpy((void*)(global_bit+21),(void*)&temp,sizeof(int));
	}

	global_bit[25]= getcx5Net0Usage();
	global_bit[26]= getcx5Net1Usage();
	global_bit[27]= getintelNet0Usage();
	global_bit[28]= getintelNet1Usage();
	global_bit[29]= getintelNet2Usage();
	global_bit[30]= getintelNet3Usage();
	global_bit[31]= getCpuTemp();

	sprintf(buff,"ipmitool raw 6 0x10");
	for(i=0;i<32;i++)
	{
		sprintf(buff,"%s 0x%x",buff,global_bit[i]);
	}
	//printf("%s\n",buff);
	system(buff);
	sleep(3);
	printf("Hardware BIT Send OK\n");
	return 0;
}
